#ifndef __REACTOR_H__
#define __REACTOR_H__

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <cstring>
#include <sys/epoll.h>
#include "ringbuff.h"
//#include "iothread.h"

class reactor;
typedef void handlerFunc(reactor* rt, int fd);

#define MAX_EVENT_NUM 1024
#define MAX_WAIT_EVENT_NUM 1024
#define MAX_READBUFF 1024 * 16
#define MAX_WRITEDBUFF 1024 * 16


struct eventLoop
{
  eventLoop()
    :fd_(0)
    ,mask_(0)
    ,flag_(0)
    ,readHandler_(nullptr)
    ,writeHandler_(nullptr)
  {
    readbuff_.initRingBuff(MAX_READBUFF);
    writebuff_.initRingBuff(MAX_WRITEDBUFF);
  }
    int fd_;//连接的fd
    int mask_;//操作 读/写
    int flag_;//是否添加到全局队列
    ringBuff  readbuff_;//读缓冲区
    ringBuff writebuff_;//写缓冲区
    handlerFunc* readHandler_;//读回调函数 (接收连接/读数据)
    handlerFunc* writeHandler_;//写回调函数 写数据
};

#define AE_NONE 0
#define AE_READABLE 1
#define AE_WRITEABLE 2

struct fireEvent
{
  fireEvent()
    :fd_(0)
    ,mask_(0)
  {}

  int fd_;//连接的fd
  int mask_;//读/写操作
};

class reactor
{
public:
  reactor()
  {
    epfd_ = epoll_create(1024);
    if(epfd_ < 0)
    {
      exit(-1);
    }
    stop_ = 0;
    num_ = 0;
    //memset(els_, 0, sizeof(eventLoop) * MAX_EVENT_NUM);
    memset(ets_, 0, sizeof(struct epoll_event) * MAX_WAIT_EVENT_NUM);
  }

  ~reactor()
  {
    close(epfd_);
  }


  int addEpollEvent(int fd, int mask)
  {
    struct epoll_event ee;
    ee.events = 0;

    int op = els_[fd].mask_ == AE_NONE ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
    mask |= els_[fd].mask_;
    if(mask & AE_READABLE) ee.events |= EPOLLIN;
    if(mask & AE_WRITEABLE) ee.events |= EPOLLOUT;
    ee.data.fd = fd;
    if(epoll_ctl(epfd_, op, fd, &ee) == -1)
        return -1;

    return 0;
  }

  void delEpollEvent(int fd, int delmask)
  {
    int mask = els_[fd].mask_ & (~delmask);
    els_[fd].mask_ = mask;
    struct epoll_event ee;
    ee.events = 0;

    if (mask & AE_READABLE) ee.events |= EPOLLIN;
    if (mask & AE_WRITEABLE) ee.events |= EPOLLOUT;
    ee.data.fd = fd;
    if(mask != AE_NONE)
    {
      epoll_ctl(epfd_, EPOLL_CTL_MOD, fd, &ee);
    }
    else 
    {
      //std::cout << "del epoll..." << fd << std::endl;
      epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, &ee);
    }
  }

  int waitEpollEvent()
  {
    memset(ets_, 0, sizeof(struct epoll_event) * MAX_WAIT_EVENT_NUM);
    int ret = epoll_wait(epfd_, ets_, MAX_WAIT_EVENT_NUM, -1);
    if(ret > 0)
    {
        num_ += ret;
        for(int i = 0; i < ret; ++i)
        {
          struct epoll_event et = ets_[i];
          int mask = 0;

          if(et.events & EPOLLIN) mask |= AE_READABLE;
          if(et.events & EPOLLOUT) mask |= AE_WRITEABLE;
          if(et.events & EPOLLERR) mask |= AE_READABLE | AE_WRITEABLE ;
          if(et.events & EPOLLHUP) mask |= AE_READABLE | AE_WRITEABLE;
          
          fired_[i].fd_ = et.data.fd;
          fired_[i].mask_ = mask;

        }
    }
    std::cout << "waitEventOnce..." << ret  << ":" << num_ << std::endl;
    return ret;
  }

  int setReactorHandler(int fd, handlerFunc* func, int mask)
  {

    if(fd > MAX_EVENT_NUM)
      return -1;
  
    eventLoop& el = els_[fd];
    el.fd_ = fd;
    addEpollEvent(fd, mask);
    el.mask_ |= mask;
    if(mask & AE_READABLE) 
     el.readHandler_ = func;
    if(mask & AE_WRITEABLE)
      el.writeHandler_ = func;

    return 0;
  }

  int getStopState()
  {
    return stop_;
  }

  void stopEventLoop()
  {
    stop_ = 1;
  }

  fireEvent* getFireEvent(int idx)
  {
    return &fired_[idx];
  }

  eventLoop* getEventLoop(int fd)
  {
    if(fd > MAX_EVENT_NUM)
      return nullptr;

    return &els_[fd];
  }

private:
    int epfd_;
    eventLoop els_[MAX_EVENT_NUM];//事件处理(回调函数)
    struct epoll_event ets_[MAX_WAIT_EVENT_NUM];// 同时能够检测多少个事件
    struct fireEvent fired_[MAX_WAIT_EVENT_NUM];
    int stop_;
    int num_;
};

#endif
